import { createBMP, drawImage as drawBMP } from "./bmp/bmp";
import { bundle, createPNG, drawImage as drawPNG } from "./png/index";
import { pngOptions, pngOptionsProps } from "./png/type";
interface ImageCombiner {
  drawCanvas(
    canvas: CanvasRenderingContext2D,
    width: number,
    height: number,
    x: number,
    y: number,
    overlying?: boolean
  ): void;
  drawCanvas(
    canvas: HTMLCanvasElement | HTMLImageElement,
    width: number,
    height: number,
    x: number,
    y: number,
    overlying?: boolean
  ): void;
  getFile(): Blob;
  download(fileName?: string): void;
}
export class BMP implements ImageCombiner {
  private dataView: DataView;
  private bWidth: number;
  private buffer: ArrayBuffer;
  private biteLength: number;
  tempCanvas = document.createElement("canvas");
  ctx = this.tempCanvas.getContext("2d");
  constructor(totalWidth: number, totalHeight: number) {
    const { dataView, bWidth, buffer, length } = createBMP(
      totalWidth,
      totalHeight
    );
    this.dataView = dataView;
    this.bWidth = bWidth;
    this.buffer = buffer;
    this.biteLength = length;
  }

  drawCanvas(
    canvas: HTMLCanvasElement | HTMLImageElement | CanvasRenderingContext2D,
    width: number,
    height: number,
    targetX: number,
    targetY: number,
    overlying?: boolean
  ) {
    if (!this.ctx) throw new Error("Canvas初始化失败");

    let ctx: undefined | CanvasRenderingContext2D;
    if (
      canvas instanceof HTMLCanvasElement ||
      canvas instanceof HTMLImageElement
    ) {
      this.tempCanvas.width = canvas.width;
      this.tempCanvas.height = canvas.height;
      this.ctx.drawImage(canvas, 0, 0);
      ctx = this.ctx;
    } else {
      ctx = canvas;
    }

    if (!ctx) throw new Error("图像捕捉失败");

    try {
      const { data } = ctx.getImageData(0, 0, width, height);
      drawBMP(
        this.dataView,
        data,
        width,
        height,
        targetX,
        targetY,
        this.bWidth,
        this.biteLength
      );
    } catch (e) {
      throw e;
    }
  }
  getFile() {
    const blob = new Blob([this.buffer], { type: "image/bmp" });
    return blob;
  }
  download(fileName: string = "下载") {
    const blob = this.getFile();
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = fileName + ".bmp";
    a.click();
  }
}

export class PNG implements ImageCombiner {
  private head: ArrayBuffer[];
  private body: ArrayBuffer;
  private options: pngOptions;
  private tempCanvas = document.createElement("canvas");
  private ctx = this.tempCanvas.getContext("2d");
  constructor(
    totalWidth: number,
    totalHeight: number,
    options: pngOptionsProps
  ) {
    const { head, body, options: newoptions } = createPNG({
      width: totalWidth,
      height: totalHeight,
      options,
    });
    this.head = head;
    this.body = body;
    this.options = newoptions;
  }
  drawCanvas(
    canvas: HTMLCanvasElement | HTMLImageElement | CanvasRenderingContext2D,
    width: number,
    height: number,
    targetX: number,
    targetY: number,
    overlying?: boolean
  ) {
    if (!this.ctx) throw new Error("Canvas初始化失败");

    let ctx: undefined | CanvasRenderingContext2D;
    if (
      canvas instanceof HTMLCanvasElement ||
      canvas instanceof HTMLImageElement
    ) {
      this.tempCanvas.width = canvas.width;
      this.tempCanvas.height = canvas.height;
      this.ctx.drawImage(canvas, 0, 0);
      ctx = this.ctx;
    } else {
      ctx = canvas;
    }

    if (!ctx) throw new Error("图像捕捉失败");

    try {
      const { data } = ctx.getImageData(0, 0, width, height);
      drawPNG(
        this.body,
        data,
        width,
        height,
        targetX,
        targetY,
        this.options.width,
        this.body.byteLength,
        overlying
      );
    } catch (e) {
      throw e;
    }
  }
  getFile() {
    return bundle(this.head, this.body, this.options);
  }
  download(fileName: string = "下载") {
    const blob = this.getFile();
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = fileName + ".png";
    a.click();
  }
}
